home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / aopt386.inc < prev    next >
Text File  |  1998-09-24  |  55KB  |  1,315 lines

  1. {
  2.     $Id: aopt386.inc,v 1.1.1.1 1998/03/25 11:18:12 root Exp $
  3.     Copyright (c) 1993-98 by Florian Klaempfl and Jonas Maebe
  4.  
  5.     This include file contains the reloading optimizer for i386+
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23.  
  24.  
  25. {$Define OptimizeMovs}
  26.  
  27. Type    TwoWords = Record
  28.             Word1, Word2: Word
  29.         End;
  30. Function Reg32(Reg: TRegister): TRegister;
  31. {Returns the 32 bit component of Reg if it exists, otherwise Reg is returned}
  32. Begin
  33.   Reg32 := Reg;
  34.   If (Reg >= R_AX)
  35.     Then
  36.       If (Reg <= R_DI)
  37.         Then Reg32 := Reg16ToReg32(Reg)
  38.         Else
  39.           If (Reg <= R_BL)
  40.             Then Reg32 := Reg8toReg32(Reg);
  41. End;
  42.  
  43. Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
  44. Begin {checks whether Ref contains a reference to Reg}
  45.   Reg := Reg32(Reg);
  46.   RegInRef := (Ref.Base = Reg) Or (Ref.Index = Reg)
  47. End;
  48.  
  49. Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
  50. {checks if Reg is used by the instruction p1}
  51. Var TmpResult: Boolean;
  52. Begin
  53.   TmpResult := False;
  54.   If (Pai(p1)^.typ = ait_instruction) Then
  55.     Begin
  56.       Case Pai386(p1)^.op1t Of
  57.         Top_Reg: TmpResult := Reg = TRegister(Pai386(p1)^.op1);
  58.         Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op1^))
  59.       End;
  60.       If Not(TmpResult) Then
  61.         Case Pai386(p1)^.op2t Of
  62.           Top_Reg:
  63.               if Pai386(p1)^.op3t<>Top_reg
  64.                 then TmpResult := Reg = TRegister(Pai386(p1)^.op2)
  65.                 else TmpResult := longint(Reg) = twowords(Pai386(p1)^.op2).word1;
  66.           Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op2^))
  67.         End;
  68.       If Not(TmpResult) Then
  69.         Case Pai386(p1)^.op3t Of
  70.           Top_Reg: TmpResult := longint(Reg) =twowords(Pai386(p1)^.op2).word2;
  71.           Top_none:;
  72.           else
  73.              internalerror($Da);
  74.        End
  75.     End;
  76.   RegInInstruction := TmpResult
  77. End;
  78.  
  79. Procedure ReloadOpt(AsmL: PaasmOutput);
  80.  
  81. Const MaxCh = 3;
  82.  
  83.       {content types}
  84.       con_Unknown = 0;
  85.       con_ref = 1;
  86.       con_const = 2;
  87.       con_symbol = 3;
  88.  
  89. Type TChange = (C_None,
  90.                 C_EAX, C_ECX, C_EDX, C_EBX, C_ESP, C_EBP, C_ESI, C_EDI,
  91. {                C_AX,  C_CX,  C_DX,  C_BX,  C_SP,  C_BP,  C_SI,  C_DI,
  92.                 C_AL,  C_CL,  C_DL,  C_BL,
  93.                 C_AH,  C_CH,  C_BH,  C_DH,
  94.                 C_DEFAULT_SEG, C_CS, C_DS, C_ES, C_FS, C_GS, C_SS,
  95. }                C_Flags, C_FPU,
  96.                 C_Op1, C_Op2, C_Op3,
  97.                 C_MemEDI);
  98.  
  99.      TAsmInstrucProp = Record
  100.                          NCh: Byte;
  101.                          Ch: Array[1..MaxCh] of TChange;
  102.                        End;
  103.  
  104.      TContent = Record
  105.                   StartMod: Pointer; {start and end of block instructions that defines the
  106.                                           content of this register; If Typ = con_const, then
  107.                                           Longint(StartMod) = value of the constant)}
  108.                    State: Word; {starts at 0, gets increased everytime the register is modified}
  109.                    NrOfMods: Byte;
  110. {                  ModReg: TRegister; }{if one register gets a block assigned from an other register,
  111.                                       this variable holds the name of that register (so it can be
  112.                                       substituted when checking the block afterwards)}
  113.                   Typ: Byte;        {con_*}
  114. {                  CanBeDestroyed: Boolean;} {if it's a register modified by the optimizer}
  115.                 End;
  116.  
  117.      TRegContent = Array[R_NO..R_EDI] Of TContent;
  118.      TRegFPUContent = Array[R_ST..R_ST7] Of TContent;
  119.  
  120.      TPaiProp = Record
  121.                   Regs: TRegContent;
  122. {                  FPURegs: TRegFPUContent;} {currently not yet used}
  123.                   LineSave: Longint;
  124.                   {can this instruction be removed?}
  125.                   CanBeRemoved: Boolean;
  126.                 End;
  127.  
  128.      PPaiProp = ^TPaiProp;
  129. {$IfDef TP}
  130.      TPaiPropBlock = Array[1..(65520 div (((SizeOf(TPaiProp)+1)div 2)*2))] Of TPaiProp;
  131. {$else}
  132.      TPaiPropBlock = Array[1..250000] Of TPaiProp;
  133. {$EndIf TP}
  134.      PPaiPropBlock = ^TPaiPropBlock;
  135.  
  136. Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
  137.    {MOV} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  138.  {MOVZX} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  139.  {MOVSX} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  140.  {LABEL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  141.    {ADD} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  142.   {CALL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  143.   {IDIV} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
  144.   {IMUL} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)), {handled separately, because several forms exist}
  145.    {JMP} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  146.    {LEA} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  147.    {MUL} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
  148.    {NEG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  149.    {NOT} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
  150.    {POP} (NCh: 2; Ch: (C_Op1, C_ESP, C_None)),
  151.  {POPAD} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  152.   {PUSH} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  153. {PUSHAD} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  154.    {RET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  155.    {SUB} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  156.   {XCHG} (NCh: 2; Ch: (C_Op1, C_Op2, C_None)), {(will be) handled seperately}
  157.    {XOR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  158.   {FILD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  159.    {CMP} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  160.     {JZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
  161.    {INC} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
  162.    {DEC} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
  163.   {SETE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  164.  {SETNE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  165.   {SETL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  166.   {SETG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  167.  {SETLE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  168.  {SETGE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  169.     {JE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  170.    {JNE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  171.     {JL} (NCh: 0; Ch: (C_None, C_None, C_None)),
  172.     {JG} (NCh: 0; Ch: (C_None, C_None, C_None)),
  173.    {JLE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  174.    {JGE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  175.     {OR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  176.    {FLD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  177.   {FADD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  178.   {FMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  179.   {FSUB} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  180.   {FDIV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  181.   {FCHS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  182.   {FLD1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  183.  {FIDIV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  184.   {CLTD} (NCh: 1; Ch: (C_EDX, C_None, C_None)),
  185.    {JNZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
  186.   {FSTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  187.    {AND} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  188.    {JNO} (NCh: 0; Ch: (C_None, C_None, C_None)),
  189.   {NOTH} (NCh: 0; Ch: (C_None, C_None, C_None)), {***???***}
  190.   {NONE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  191.  {ENTER} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  192.  {LEAVE} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  193.    {CLD} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  194.   {MOVS} (NCh: 3; Ch: (C_ESI, C_EDI, C_MemEDI)),
  195.    {REP} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  196.    {SHL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  197.    {SHR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  198.  {BOUND} (NCh: 0; Ch: (C_None, C_None, C_None)),
  199.    {JNS} (NCh: 0; Ch: (C_None, C_None, C_None)),
  200.     {JS} (NCh: 0; Ch: (C_None, C_None, C_None)),
  201.     {JO} (NCh: 0; Ch: (C_None, C_None, C_None)),
  202.    {SAR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  203.   {TEST} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  204.   {FCOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  205.  {FCOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  206. {FCOMPP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  207.   {FXCH} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  208.  {FADDP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  209.  {FMULP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  210.  {FSUBP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  211.  {FDIVP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  212.  {FNSTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  213.   {SAHF} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  214. {FDIVRP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  215. {FSUBRP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  216.   {SETC} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  217.  {SETNC} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  218.     {JC} (NCh: 0; Ch: (C_None, C_None, C_None)),
  219.    {JNC} (NCh: 0; Ch: (C_None, C_None, C_None)),
  220.     {JA} (NCh: 0; Ch: (C_None, C_None, C_None)),
  221.    {JAE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  222.     {JB} (NCh: 0; Ch: (C_None, C_None, C_None)),
  223.    {JBE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  224.   {SETA} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  225.  {SETAE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  226.   {SETB} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  227.  {SETBE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  228.    {AAA} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
  229.    {AAD} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
  230.    {AAM} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
  231.    {AAS} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
  232.    {CBW} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  233.    {CDQ} (NCh: 2; Ch: (C_EAX, C_EDX, C_None)),
  234.    {CLC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  235.    {CLI} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  236.   {CLTS} (NCh: 0; Ch: (C_None, C_None, C_None)),
  237.    {CMC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  238.    {CWD} (NCh: 2; Ch: (C_EAX, C_EDX, C_None)),
  239.   {CWDE} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  240.    {DAA} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  241.    {DAS} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  242.    {HLT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  243.   {IRET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  244.   {LAHF} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  245.   {LODS} (NCh: 2; Ch: (C_EAX, C_ESI, C_None)),
  246.   {LOCK} (NCh: 0; Ch: (C_None, C_None, C_None)),
  247.    {NOP} (NCh: 0; Ch: (C_None, C_None, C_None)),
  248.  {PUSHA} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  249.  {PUSHF} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  250. {PUSHFD} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  251.    {STC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  252.    {STD} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  253.    {STI} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  254.   {STOS} (NCh: 2; Ch: (C_MemEDI, C_EDI, C_None)),
  255.   {WAIT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  256.   {XLAT} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  257.  {XLATB} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  258.  {MOVSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  259. {MOVSBL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  260. {MOVSBW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  261. {MOVSWL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  262.  {MOVZB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  263. {MOVZWL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  264.   {POPA} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  265.     {IN} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  266.    {OUT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  267.    {LDS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  268.    {LCS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  269.    {LES} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  270.    {LFS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  271.    {LGS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  272.    {LSS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  273.   {POPF} (NCh: 2; Ch: (C_Flags, C_ESP, C_None)),
  274.    {SBB} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  275.    {ADC} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  276.    {DIV} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
  277.    {ROR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  278.    {ROL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  279.    {RCL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  280.    {RCR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  281.    {SAL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  282.   {SHLD} (NCh: 2; Ch: (C_Op3, C_Flags, C_None)),
  283.   {SHRD} (NCh: 2; Ch: (C_Op3, C_Flags, C_None)),
  284.  {LCALL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  285.   {LJMP} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  286.   {LRET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  287.   {JNAE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  288.    {JNB} (NCh: 0; Ch: (C_None, C_None, C_None)),
  289.    {JNA} (NCh: 0; Ch: (C_None, C_None, C_None)),
  290.   {JNBE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  291.     {JP} (NCh: 0; Ch: (C_None, C_None, C_None)),
  292.    {JNP} (NCh: 0; Ch: (C_None, C_None, C_None)),
  293.    {JPE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  294.    {JPO} (NCh: 0; Ch: (C_None, C_None, C_None)),
  295.   {JNGE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  296.    {JNG} (NCh: 0; Ch: (C_None, C_None, C_None)),
  297.    {JNL} (NCh: 0; Ch: (C_None, C_None, C_None)),
  298.   {JNLE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  299.   {JCXZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
  300.  {JECXZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
  301.   {LOOP} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  302.   {CMPS} (NCh: 3; Ch: (C_ESI, C_EDI, C_Flags)),
  303.    {INS} (NCh: 1; Ch: (C_EDI, C_None, C_None)),
  304.   {OUTS} (NCh: 1; Ch: (C_ESI, C_None, C_None)),
  305.   {SCAS} (NCh: 2; Ch: (C_EDI, C_Flags, C_None)),
  306.    {BSF} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  307.    {BSR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  308.     {BT} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  309.    {BTC} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  310.    {BTR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  311.    {BTS} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  312.    {INT} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  313.   {INT3} (NCh: 0; Ch: (C_None, C_None, C_None)),
  314.   {INTO} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  315. {BOUNDL} (NCh: 0; Ch: (C_None, C_None, C_None)),
  316. {BOUNDW} (NCh: 0; Ch: (C_None, C_None, C_None)),
  317.  {LOOPZ} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  318.  {LOOPE} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  319. {LOOPNZ} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  320. {LOOPNE} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  321.   {SETO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  322.  {SETNO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  323. {SETNAE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  324.  {SETNB} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  325.   {SETZ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  326.  {SETNZ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  327.  {SETNA} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  328. {SETNBE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  329.   {SETS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  330.  {SETNS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  331.   {SETP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  332.  {SETPE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  333.  {SETNP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  334.  {SETPO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  335. {SETNGE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  336.  {SETNL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  337.  {SETNG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  338. {SETNLE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  339.   {ARPL} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  340.    {LAR} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  341.   {LGDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  342.   {LIDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  343.   {LLDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  344.   {LMSW} (NCh: 0; Ch: (C_None, C_None, C_None)),
  345.    {LSL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  346.    {LTR} (NCh: 0; Ch: (C_None, C_None, C_None)),
  347.   {SGDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  348.   {SIDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  349.   {SLDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  350.   {SMSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  351.   {STR}  (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  352.   {VERR} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  353.   {VERW} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  354.   {FABS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  355.   {FBLD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  356.  {FBSTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  357.  {FCLEX} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  358. {FNCLEX} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  359.   {FCOS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  360. {FDECSTP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  361.  {FDISI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  362. {FNDISI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  363.  {FDIVR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  364.   {FENI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  365.  {FNENI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  366.  {FFREE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  367.  {FIADD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  368.  {FICOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  369. {FICOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  370. {FIDIVR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  371.  {FIMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  372. {FINCSTP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  373.  {FINIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  374. {FNINIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  375.   {FIST} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  376.  {FISTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  377.  {FISUB} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  378.  {FSUBR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  379.  {FLDCW} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  380. {FLDENV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  381. {FLDLG2} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  382. {FLDLN2} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  383. {FLDL2E} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  384. {FLDL2T} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  385.  {FLDPI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  386.   {FLDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  387.   {FLDZ} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  388.   {FNOP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  389. {FPATAN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  390.  {FPREM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  391. {FPREM1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  392.  {FPTAN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  393. {FRNDINT}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  394. {FRSTOR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  395.  {FSAVE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  396. {FNSAVE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  397. {FSCALE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  398. {FSETPM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  399.   {FSIN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  400. {FSINCOS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  401.  {FSQRT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  402.    {FST} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  403.  {FSTCW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  404. {FNSTCW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  405. {FSTENV} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  406. {FNSTENV}(NCh: 1; Ch: (C_Op1, C_None, C_None)),
  407.  {FSTSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  408. {FNSTSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  409.   {FTST} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  410.  {FUCOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  411. {FUCOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  412. {FUCOMPP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  413.  {FWAIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  414.   {FXAM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  415. {FXTRACT}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  416.  {FYL2X} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  417. {FYL2XP1}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  418.  {F2XM1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  419.  {FILDQ} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  420.  {FILDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  421.  {FILDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  422.   {FLDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  423.   {FLDT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  424.  {FISTQ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  425.  {FISTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  426.  {FISTL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  427.   {FSTL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  428.   {FSTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  429.  {FSTPS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  430. {FISTPL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  431.  {FSTPL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  432. {FISTPS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  433. {FISTPQ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  434.  {FSTPT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  435. {FCOMPS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  436. {FICOMPL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  437. {FCOMPL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  438. {FICOMPS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  439.  {FCOMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  440. {FICOML} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  441.  {FCOML} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  442. {FICOMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  443. {FIADDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  444.  {FADDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  445. {FIADDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  446. {FISUBL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  447.  {FSUBL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  448. {FISUBS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  449.  {FSUBS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  450.  {FSUBR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  451. {FSUBRS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  452. {FISUBRL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  453. {FSUBRL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  454. {FISUBRS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  455.  {FMULS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  456.  {FIMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  457.  {FMULL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  458. {FIMULS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  459. {FIDIVS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  460. {FIDIVL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  461.  {FDIVL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  462. {FIDIVS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  463. {FDIVRS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  464. {FIDIVRL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  465. {FDIVRL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  466. {FIDIVRS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  467.   {REPE} (NCh: 0; Ch: (C_ECX, C_None, C_None)),
  468.  {REPNE} (NCh: 0; Ch: (C_ECX, C_None, C_None)),
  469.  {FADDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  470.  {POPFD} (NCh: 2; Ch: (C_ESP, C_Flags, C_None)),
  471. {below are the MMX instructions}
  472. {A_EMMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  473. {A_MOVD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  474. {A_MOVQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  475. {A_PACKSSDW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  476. {A_PACKSSWB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  477. {A_PACKUSWB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  478. {A_PADDB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  479. {A_PADDD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  480. {A_PADDSB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  481. {A_PADDSW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  482. {A_PADDUSB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  483. {A_PADDUSW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  484. {A_PADDW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  485. {A_PAND} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  486. {A_PANDN} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  487. {A_PCMPEQB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  488. {A_PCMPEQD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  489. {A_PCMPEQW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  490. {A_PCMPGTB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  491. {A_PCMPGTD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  492. {A_PCMPGTW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  493. {A_PMADDWD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  494. {A_PMULHW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  495. {A_PMULLW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  496. {A_POR} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  497. {A_PSLLD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  498. {A_PSLLQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  499. {A_PSLLW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  500. {A_PSRAD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  501. {A_PSRAW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  502. {A_PSRLD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  503. {A_PSRLQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  504. {A_PSRLW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  505. {A_PSUBB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  506. {A_PSUBD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  507. {A_PSUBSB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  508. {A_PSUBSW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  509. {A_PSUBUSB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  510. {A_PSUBUSW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  511. {A_PSUBW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  512. {A_PUNPCKHBW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  513. {A_PUNPCKHDQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  514. {A_PUNPCKHWD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  515. {A_PUNPCKLBW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  516. {A_PUNPCKLDQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  517. {A_PUNPCKLWD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  518. {A_PXOR} (NCh: 255; Ch: (C_FPU, C_None, C_None)));
  519.  
  520. Var NrOfPaiObjs, NrOfPaiFast: Longint;
  521.     PaiPropBlock: PPaiPropBlock;
  522.     NrOfInstrSinceLastMod: Array[R_EAX..R_EDI] Of Byte;
  523.  
  524. Function TCh2Reg(Ch: TChange): TRegister;
  525. {converts a TChange variable to a TRegister}
  526. Begin
  527.   If (CH <= C_EDI)
  528.     Then TCh2Reg := TRegister(Byte(Ch))
  529.     Else InternalError($db)
  530. End;
  531.  
  532. Procedure DestroyReg(p1: pai; Reg: TRegister);
  533. {Destroys the contents of the register Reg in the PPaiProp of P}
  534. Var TmpState: Longint;
  535. Begin
  536.   Reg := Reg32(Reg);
  537.   NrOfInstrSinceLastMod[Reg] := 0;
  538.   If (Reg >= R_EAX) And (Reg <= R_EDI)
  539.     Then
  540.       Begin
  541.         TmpState := PPaiProp(p1^.line)^.Regs[Reg].State+1;
  542.         FillChar(PPaiProp(p1^.line)^.Regs[Reg], SizeOf(TContent), 0);
  543.         PPaiProp(p1^.line)^.Regs[Reg].State := TmpState;
  544.       End;
  545. End;
  546.  
  547. (*Function FindZeroreg(p: Pai; Var Result: TRegister): Boolean;
  548. {Finds a register which contains the constant zero}
  549. Var Counter: TRegister;
  550. Begin
  551.   Counter := R_EAX;
  552.   FindZeroReg := True;
  553.   While (Counter <= R_EDI) And
  554.         ((PPaiProp(p^.line)^.Regs[Counter].Typ <> Con_Const) or
  555.          (PPaiProp(p^.line)^.Regs[Counter].StartMod <> Pointer(0))) Do
  556.     Inc(Byte(Counter));
  557.   If (PPaiProp(p^.line)^.Regs[Counter].Typ = Con_Const) And
  558.      (PPaiProp(p^.line)^.Regs[Counter].StartMod = Pointer(0))
  559.     Then Result := Counter
  560.     Else FindZeroReg := False;
  561. End;*)
  562.  
  563. Procedure DestroyRefs(p: pai; Const Ref: TReference; WhichRegNot: TRegister);
  564. {destroys all registers which possibly contain a reference to Ref}
  565. Var Counter: TRegister;
  566. Begin
  567. WhichRegNot := Reg32(WhichRegNot);
  568. If (Ref.base <> R_NO) Or
  569.    (Ref.index <> R_NO)
  570.   Then
  571.     Begin
  572.       If (Ref.base = ProcInfo.FramePointer)
  573.         Then
  574. {write something to a parameter or a local variable}
  575.           For Counter := R_EAX to R_EDI Do
  576.             With PPaiProp(p^.line)^.Regs[Counter] Do
  577.               Begin
  578.                 If (Counter <> WhichRegNot) And
  579.                    (typ = Con_Ref) And
  580.                    (Pai(StartMod)^.typ = ait_instruction) And
  581.                    (Pai386(StartMod)^.op1t = top_ref) And
  582.                    (RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref) Or
  583.                    (Not(cs_UncertainOpts in AktSwitches) And
  584.                     (NrOfMods <> 1)))
  585.                   Then DestroyReg(p, Counter)
  586.               End
  587.         Else
  588.           {writing something to a pointer location}
  589.           For Counter := R_EAX to R_EDI Do
  590.             With PPaiProp(p^.line)^.Regs[Counter] Do
  591.             If (Counter <> WhichRegNot) And
  592.                (typ = Con_Ref) And
  593.                (Not(cs_UncertainOpts in AktSwitches) Or
  594.                 (Ref.Base = R_EDI) Or
  595.                 (Not((NrOfMods = 1) And
  596.                 (Pai(StartMod)^.typ = ait_instruction) And
  597.                 (Pai386(StartMod)^.op1t = top_ref) And
  598.                 (PReference(Pai386(StartMod)^.op1)^.base = ProcInfo.FramePointer))))
  599.               Then
  600.                 DestroyReg(p, Counter) {we don't know what memory location the reference points to,
  601.                                       so we just destroy every register which contains a memory
  602.                                       reference}
  603.     End
  604.   Else {the ref is a var name or we just have a reference an absolute offset}
  605.     Begin
  606.       For Counter := R_EAX to R_EDI Do
  607.         If (Counter <> WhichRegNot) And
  608.            (PPaiProp(p^.line)^.Regs[Counter].typ = Con_Ref) And
  609.            (Not(cs_UncertainOpts in AktSwitches) Or
  610.             RefsEqual(Ref,
  611.                      TReference(Pai386(PPaiProp(p^.line)^.Regs[Counter].StartMod)^.op1^))) Then
  612.           DestroyReg(p, Counter)
  613.     End;
  614. End;
  615.  
  616. {$IfDef OptimizeMovs}
  617.  
  618. Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean;
  619. Begin {checks whether the two ops are equal}
  620.   Case typ Of
  621.     Top_Reg, Top_Const: OpsEqual := op1 = op2;
  622.     Top_Ref: OpsEqual := RefsEqual(TReference(op1^), TReference(op2^));
  623.     Top_None: OpsEqual := True
  624.     Else OpsEqual := False
  625.   End;
  626. End;
  627.  
  628. Function RegsSameContent(p1, p2: Pai; Reg: TRegister): Boolean;
  629. {checks whether Reg has the same content in the PPaiProp of p1 and p2}
  630. Begin
  631.   Reg := Reg32(Reg);
  632.   RegsSameContent :=
  633.     PPaiProp(p1^.line)^.Regs[Reg].State =
  634.     PPaiProp(p2^.line)^.Regs[Reg].State;
  635. End;
  636.  
  637. Function InstructionsEqual(p1, p2: Pai): Boolean;
  638. Begin {checks whether two Pai386 instructions are equal}
  639.   InstructionsEqual :=
  640.     Assigned(p1) And Assigned(p2) And
  641.     (Pai(p1)^.typ = ait_instruction) And
  642.     (Pai(p1)^.typ = ait_instruction) And
  643.     (Pai386(p1)^._operator = Pai386(p2)^._operator) And
  644.     (Pai386(p1)^.op1t = Pai386(p2)^.op1t) And
  645.     (Pai386(p1)^.op2t = Pai386(p2)^.op2t) And
  646.     OpsEqual(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1) And
  647.     OpsEqual(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2)
  648. End;
  649.  
  650. Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint): Boolean;
  651. {checks whether the current instruction sequence (starting with p) and the
  652.  one between StartMod and EndMod of Reg are the same. If so, the number of
  653.  instructions that match is stored in Found and true is returned, otherwise
  654.  Found holds the number of instructions between StartMod and EndMod and false
  655.  is returned}
  656. Var hp2, hp3, EndMod: Pai;
  657.     TmpResult: Boolean;
  658.     RegsNotYetChecked: Set Of TRegister;
  659.     Counter: Byte;
  660.  
  661. Function NoChangedRegInRef(oldp, newp: Pai): Boolean;
  662. Var TmpP: Pai;
  663. {checks if the first operator of newp is a reference and in that case checks
  664.  whether that reference includes regs that have been changed since oldp. This
  665.  to avoid wrong optimizations like
  666.  
  667.  movl 8(%epb), %eax                          movl 8(%epb), %eax
  668.  movl 12(%epb), %edx                         movl 12(%epb), %edx
  669.  movl (%eax,%edx,1), %edi                    movl (%eax,%edx,1), %edi
  670.  pushl %edi              being converted to  pushl %edi
  671.  movl 8(%epb), %eax                          movl 16(%ebp), %edx
  672.  movl 16(%epb), %edx                         pushl %edi
  673.  movl (%eax,%edx,1), %edi
  674.  pushl %edi
  675.  
  676. because first is checked whether %eax isn't changed (it isn't) and
  677. consequently all instructions containg %eax are removed}
  678. Begin
  679.   TmpResult := True;
  680.   If (Pai(oldp)^.typ = ait_instruction) Then {oldp and newp are the same instruction}
  681.     Case Pai386(oldp)^.op1t Of
  682.       Top_Reg:
  683.         If (Reg32(TRegister(Pai386(oldp)^.op1)) in RegsNotYetChecked) Then
  684.           Begin
  685.             RegsNotYetChecked := RegsNotYetChecked - [Reg32(TRegister(Pai386(oldp)^.op1))];
  686.             If Assigned(newp^.Last)
  687.               Then
  688.                 Begin
  689.                   TmpP := Pai(newp^.last);
  690.                   While Assigned (TmpP^.Last) And
  691.                         PPaiProp(TmpP^.Line)^.CanBeRemoved Do
  692.                     TmpP := Pai(TmpP^.Last);
  693.                   TmpResult := Assigned(TmpP) And
  694.                                RegsSameContent(oldp, TmpP, Reg32(TRegister(Pai386(oldp)^.op1)))
  695.                 End
  696.               Else TmpResult := False;
  697.           End;
  698.       Top_Ref:
  699.         With TReference(Pai386(oldp)^.op1^) Do
  700.           Begin
  701.             If (Base in RegsNotYetChecked) And
  702.                (Base <> R_NO) Then
  703.               Begin
  704.                 RegsNotYetChecked := RegsNotYetChecked - [Base];
  705.                 If Assigned(newp^.Last)
  706.                   Then
  707.                     Begin
  708.                       TmpP := Pai(newp^.last);
  709.                       While Assigned (TmpP^.Last) And
  710.                             PPaiProp(TmpP^.Line)^.CanBeRemoved Do
  711.                         TmpP := Pai(TmpP^.Last);
  712.                       TmpResult := Assigned(TmpP) And
  713.                                    RegsSameContent(oldp, TmpP, Base)
  714.                     End
  715.                   Else TmpResult := False;
  716.               End;
  717.             If TmpResult And
  718.                (Index <> R_NO) And
  719.                (Index in RegsNotYetChecked) Then
  720.               Begin
  721.                 RegsNotYetChecked := RegsNotYetChecked - [Index];
  722.                 If Assigned(newp^.Last)
  723.                   Then
  724.                     Begin
  725.                       TmpP := Pai(newp^.last);
  726.                       While Assigned (TmpP^.Last) And
  727.                             PPaiProp(TmpP^.Line)^.CanBeRemoved Do
  728.                         TmpP := Pai(TmpP^.Last);
  729.                       TmpResult := Assigned(TmpP) And
  730.                                    RegsSameContent(oldp, TmpP, Index)
  731.                     End
  732.                   Else TmpResult := False;
  733.               End;
  734.           End;
  735.     End;
  736.   NoChangedRegInRef := TmpResult;
  737. End;
  738.  
  739. Begin {CheckSequence}
  740.   Reg := Reg32(Reg);
  741.   Found := 0;
  742.   hp2 := p;
  743.   hp3 := PPaiProp(Pai(p^.last)^.line)^.Regs[Reg].StartMod;
  744.   EndMod := PPaiProp(Pai(p^.last)^.line)^.Regs[Reg].StartMod;
  745.   RegsNotYetChecked := [R_EAX..R_EDI];
  746.   For Counter := 2 to PPaiProp(Pai(p^.last)^.line)^.Regs[Reg].NrOfMods Do
  747.     EndMod := Pai(EndMod^.Next);
  748.   While (Found <> PPaiProp(Pai(p^.last)^.line)^.Regs[Reg].NrOfMods) And
  749.          InstructionsEqual(hp2, hp3) And
  750.          NoChangedRegInRef(EndMod, hp2) Do
  751.     Begin
  752.       hp2 := Pai(hp2^.next);
  753.       hp3 := Pai(hp3^.next);
  754.       Inc(Found)
  755.     End;
  756.   If (Found <> PPaiProp(Pai(p^.last)^.line)^.Regs[Reg].NrOfMods)
  757.      Then
  758.        Begin
  759.          CheckSequence := False;
  760.          If (found > 0) then
  761.  {this is correct because we only need to turn off the CanBeRemoved flag
  762.   when an instruction has already been processed by CheckSequence
  763.   (otherwise CanBeRemoved can't be true, or can't have to be turned off).
  764.   If it has already been processed by checkSequence and flagged to be
  765.   removed, it means that it has been checked against a previous sequence
  766.   and that it was equal (otherwise CheckSequence would have returned false
  767.   and the instruction wouldn't have been removed). If this "If found > 0"
  768.   check is left out, incorrect optimizations are performed.}
  769.            Found := PPaiProp(Pai(p)^.line)^.Regs[Reg].NrOfMods
  770.        End
  771.      Else CheckSequence := True;
  772. End; {CheckSequence}
  773.  
  774. {$Endif OptimizeMovs}
  775.  
  776. Procedure DestroyAllRegs(p: Pai);
  777. Var Counter: TRegister;
  778. Begin {initializes/desrtoys all registers}
  779.   For Counter := R_EAX To R_EDI Do
  780.     DestroyReg(p, Counter);
  781. End;
  782.  
  783. Procedure Destroy(PaiObj: Pai; opt: Longint; Op: Pointer);
  784. Begin
  785.   Case opt Of
  786.     top_reg: DestroyReg(PaiObj, TRegister(Op));
  787.     top_ref: DestroyRefs(PaiObj, TReference(Op^), R_NO);
  788.     top_symbol:;
  789.   End;
  790. End;
  791.  
  792. Function CreateRegs(First: Pai): Pai;
  793. {Starts creating the reg contents for the instructions starting with p.
  794. Returns the last pai which has been processed}
  795. Var
  796.     TmpProp: PPaiProp;
  797.     Cnt, InstrCnt: Longint;
  798.     InstrProp: TAsmInstrucProp;
  799.     p: Pai;
  800.     TmpRef: TReference;
  801.     TmpReg: TRegister;
  802. Begin
  803.   p := First;
  804.   InstrCnt := 1;
  805.   FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0);
  806.   While Assigned(p) Do
  807.     Begin
  808.       CreateRegs := p;
  809.       If (InstrCnt <= NrOfPaiFast)
  810.         Then TmpProp := @PaiPropBlock^[InstrCnt]
  811.         Else New(TmpProp);
  812.       If (p <> First)
  813.         Then TmpProp^ := PPaiProp(Pai(p^.last)^.line)^
  814.         Else FillChar(TmpProp^, SizeOf(TmpProp^), 0);
  815.       TmpProp^.LineSave := p^.line;
  816.       PPaiProp(p^.line) := TmpProp;
  817.       For TmpReg := R_EAX To R_EDI Do
  818.         Inc(NrOfInstrSinceLastMod[TmpReg]);
  819.       Case p^.typ Of
  820.         ait_label: DestroyAllRegs(p);
  821.         ait_labeled_instruction, ait_stabs, ait_stabn,
  822.         ait_stab_function_name:; {nothing changes}
  823.         ait_instruction:
  824.           Begin
  825.             InstrProp := AsmInstr[Pai386(p)^._operator];
  826.             Case Pai386(p)^._operator Of
  827. {$IfDef OptimizeMovs}
  828.               A_MOV, A_MOVZX, A_MOVSX:
  829.                 Begin
  830.                   Case Pai386(p)^.op1t Of
  831.                     Top_Reg:
  832.                       Case Pai386(p)^.op2t Of
  833.                         Top_Reg:
  834.                           Begin
  835.                             DestroyReg(p, TRegister(Pai386(p)^.op2));
  836. {                            TmpProp^.Regs[TRegister(Pai386(p)^.op2)] :=
  837.                               TmpProp^.Regs[TRegister(Pai386(p)^.op1)];
  838.                             If (TmpProp^.Regs[TRegister(Pai386(p)^.op2)].ModReg = R_NO) Then
  839.                               TmpProp^.Regs[TRegister(Pai386(p)^.op2)].ModReg :=
  840.                                 Tregister(Pai386(p)^.op1);}
  841.                           End;
  842.                         Top_Ref: DestroyRefs(p, TReference(Pai386(p)^.op2^), TRegister(Pai386(p)^.op1));
  843.                       End;
  844.                     Top_Ref:
  845.                       Begin {destination is always a register in this case}
  846.                         TmpReg := Reg32(TRegister(Pai386(p)^.op2));
  847.                         If (RegInRef(TmpReg, TReference(Pai386(p)^.op1^)))
  848.                           Then
  849.                             Begin
  850.                               With PPaiProp(Pai(p)^.line)^.Regs[TmpReg] Do
  851.                                 Begin
  852.                                   Inc(State);
  853.  {also store how many instructions are part of the sequence in the first
  854.   instructions PPaiProp, so it can be easily accessed from within
  855.   CheckSequence}
  856.                                   If (typ <> Con_Ref) Then
  857.                                     Begin
  858.                                       typ := Con_Ref;
  859.                                       StartMod := p;
  860.                                     End;
  861.                                   Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
  862.                                   PPaiProp(Pai(StartMod)^.line)^.Regs[TmpReg].NrOfMods := NrOfMods;
  863.                                   NrOfInstrSinceLastMod[TmpReg] := 0;
  864.                                 End;
  865.                             End
  866.                           Else
  867.                             Begin
  868.                               DestroyReg(p, TmpReg);
  869.                               With PPaiProp(Pai(p)^.line)^.Regs[TmpReg] Do
  870.                                 Begin
  871.                                   Typ := Con_Ref;
  872.                                   StartMod := p;
  873.                                   NrOfMods := 1;
  874.                                 End;
  875.                             End;
  876.                       End;
  877.                     Top_Const:
  878.                       Begin
  879.                         Case Pai386(p)^.op2t Of
  880.                           Top_Reg:
  881.                             Begin
  882.                               TmpReg := Reg32(TRegister(Pai386(p)^.op2));
  883.                               With TmpProp^.Regs[TmpReg] Do
  884.                                 Begin
  885.                                 {it doesn't matter that the state is changed,
  886.                                  it isn't looked at when removing constant reloads}
  887.                                   DestroyReg(p, TmpReg);
  888.                                   typ := Con_Const;
  889.                                   StartMod := Pai386(p)^.op1;
  890.                                 End
  891.                             End;
  892.                           Top_Ref: DestroyRefs(P, TReference(Pai386(p)^.op2^), R_NO);
  893.                         End;
  894.                       End;
  895.                 End;
  896.               End;
  897. {$EndIf OptimizeMovs}
  898.               A_IMUL:
  899.                 Begin
  900.                   If (Pai386(p)^.Op3t = top_none)
  901.                    Then
  902.                      If (Pai386(p)^.Op2t = top_none)
  903.                        Then
  904.                          Begin
  905.                            DestroyReg(p, R_EAX);
  906.                            DestroyReg(p, R_EDX)
  907.                          End
  908.                        Else
  909.                          Begin
  910.                            If (Pai386(p)^.Op2t = top_reg) Then
  911.                              DestroyReg(p, TRegister(Pai386(p)^.Op2));
  912.                          End
  913.                    Else If (Pai386(p)^.Op3t = top_reg) Then
  914.                           DestroyReg(p, TRegister(longint(twowords(Pai386(p)^.Op2).word2)));
  915.                 End;
  916.               A_XOR:
  917.                 Begin
  918.                   If (Pai386(p)^.op1t = top_reg) And
  919.                      (Pai386(p)^.op2t = top_reg) And
  920.                      (Pai386(p)^.op1 = Pai386(p)^.op2)
  921.                     Then
  922.                       Begin
  923.                         DestroyReg(p, Tregister(Pai386(p)^.op1));
  924.                         TmpProp^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ := Con_Const;
  925.                         TmpProp^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod := Pointer(0)
  926.                       End
  927.                     Else Destroy(p, Pai386(p)^.op2t, Pai386(p)^.op2);
  928.                 End
  929.               Else
  930.                 Begin
  931.                   If InstrProp.NCh <> 255
  932.                     Then
  933.                       For Cnt := 1 To InstrProp.NCh Do
  934.                         Case InstrProp.Ch[Cnt] Of
  935.                           C_None:;
  936.                           C_Op1: Destroy(p, Pai386(p)^.op1t, Pai386(p)^.op1);
  937.                           C_Op2: Destroy(p, Pai386(p)^.op2t, Pai386(p)^.op2);
  938.                           C_Op3: Destroy(p, Pai386(p)^.op2t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word2)));
  939.                           C_MemEDI:
  940.                             Begin
  941.                               FillChar(TmpRef, SizeOf(TmpRef), 0);
  942.                               TmpRef.Base := R_EDI;
  943.                               DestroyRefs(p, TmpRef, R_NO)
  944.                             End;
  945.                           C_EAX..C_EDI: DestroyReg(p, TCh2Reg(InstrProp.Ch[Cnt]));
  946.                           C_Flags, C_FPU:;
  947.                         End
  948.                     Else
  949.                       Begin
  950.                         DestroyAllRegs(p);
  951.                       End;
  952.                 End;
  953.             End;
  954.           End
  955.         Else
  956.           Begin
  957.             DestroyAllRegs(p);
  958.           End;
  959.       End;
  960.       Inc(InstrCnt);
  961.       p := Pai(p^.next);
  962.     End;
  963. End;
  964.  
  965. Procedure OptimizeBlock(First, Last: Pai);
  966. {marks the instructions that can be removed by RemoveInstructs. They're not
  967.  removed immediately because sometimes an instruction needs to be checked in
  968.  two different sequences}
  969. Var Cnt, Cnt2: Longint;
  970.     p, hp1, hp2: Pai;
  971. Begin
  972.   p := First;
  973.   While (p <> Pai(Last^.Next)) Do
  974.     Begin
  975.       Case p^.typ Of
  976.         ait_label, ait_labeled_instruction:;
  977.         ait_instruction:
  978.           Begin
  979.             Case Pai386(p)^._operator Of
  980. {$IfDef OptimizeMovs}
  981.               A_MOV{, A_MOVZX, A_MOVSX}:
  982.                 Begin
  983.                   Case Pai386(p)^.op1t Of
  984. {                    Top_Reg:
  985.                       Case Pai386(p)^.op2t Of
  986.                         Top_Reg:;
  987.                         Top_Ref:;
  988.                       End;}
  989.                     Top_Ref:
  990.                       Begin {destination is always a register in this case}
  991.                         With PPaiProp(p^.line)^.Regs[Reg32(Tregister(Pai386(p)^.op2))] Do
  992.                           Begin
  993.                             If Assigned(p^.last) And
  994.                                (PPaiProp(Pai(p^.last)^.line)^.Regs[Reg32(TRegister(Pai386(p)^.op2))].typ = con_ref) Then
  995.    {so we don't try to check a sequence when the register only contains a constant}
  996.                                If CheckSequence(p, TRegister(Pai386(p)^.op2), Cnt) And
  997.                                   (Cnt > 0)
  998.                                  Then
  999.                                    Begin
  1000.                                      hp1 := nil;
  1001.    {although it's perfectly ok to remove an instruction which doesn't contain
  1002.     the register that we've just checked (CheckSequence takes care of that),
  1003.     the sequence containing this other register should also be completely
  1004.     checked and removed, otherwise we may get situations like this:
  1005.  
  1006.       movl 12(%ebp), %edx                       movl 12(%ebp), %edx
  1007.       movl 16(%ebp), %eax                       movl 16(%ebp), %eax
  1008.       movl 8(%edx), %edx                        movl 8(%edx), %edx
  1009.       movl (%eax), eax                          movl (%eax), eax
  1010.       cmpl %eax, %edx                           cmpl %eax, %edx
  1011.       jnz  l123           getting converted to  jnz  l123
  1012.       movl 12(%ebp), %edx                       movl 4(%eax), eax
  1013.       movl 16(%ebp), %eax
  1014.       movl 8(%edx), %edx
  1015.       movl 4(%eax), eax}
  1016.                                      hp2 := p;
  1017.                                      For Cnt2 := 1 to Cnt Do
  1018.                                        Begin
  1019.                                          If Not(Pai(p)^.typ In [ait_stabs, ait_stabn, ait_stab_function_name]) Then
  1020.                                            Begin
  1021.                                              If (hp1 = nil) And
  1022.                                                 Not(RegInInstruction(Tregister(Pai386(hp2)^.op2), p))
  1023.                                                Then hp1 := p;
  1024.                                              PPaiProp(p^.line)^.CanBeRemoved := True;
  1025.                                            End;
  1026.                                          p := Pai(p^.next);
  1027.                                        End;
  1028.                                      If hp1 <> nil Then p := hp1;
  1029.                                      Continue;
  1030.                                    End
  1031.                                  Else
  1032.                                    If (Cnt > 0) And
  1033.                                       (PPaiProp(p^.line)^.CanBeRemoved) Then
  1034.                                      Begin
  1035.                                        hp2 := p;
  1036.                                        For Cnt2 := 1 to Cnt Do
  1037.                                          Begin
  1038.                                            If RegInInstruction(Tregister(Pai386(hp2)^.op2), p)
  1039.                                              Then PPaiProp(p^.Line)^.CanBeRemoved := False;
  1040.                                            p := Pai(p^.Next)
  1041.                                          End;
  1042.                                        Continue;
  1043.                                      End;
  1044.                           End;
  1045.                       End;
  1046.                     Top_Const:
  1047.                       Begin
  1048.                         Case Pai386(p)^.op2t Of
  1049.                           Top_Reg:
  1050.                             Begin
  1051.                               If Assigned(p^.last) Then
  1052.                                 With PPaiProp(Pai(p^.last)^.line)^.Regs[Reg32(TRegister(Pai386(p)^.op2))] Do
  1053.                                   If (Typ = Con_Const) And
  1054.                                      (StartMod = Pai386(p)^.op1) Then
  1055.                                     PPaiProp(p^.line)^.CanBeRemoved := True;
  1056.                             End;
  1057.                           Top_Ref:;
  1058.                         End;
  1059.                       End;
  1060.                   End;
  1061.                 End;
  1062. {$EndIf OptimizeMovs}
  1063.               A_XOR:
  1064.                 Begin
  1065.                   If (Pai386(p)^.op1t = top_reg) And
  1066.                      (Pai386(p)^.op2t = top_reg) And
  1067.                      (Pai386(p)^.op1 = Pai386(p)^.op2) And
  1068.                      Assigned(p^.last) And
  1069.                      (PPaiProp(Pai(p^.last)^.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ = con_const) And
  1070.                      (PPaiProp(Pai(p^.last)^.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod = Pointer(0))
  1071.                     Then PPaiProp(p^.line)^.CanBeRemoved := True
  1072.                 End
  1073.             End
  1074.           End;
  1075.       End;
  1076.       p := Pai(p^.next);
  1077.     End;
  1078. End;
  1079.  
  1080. Procedure RemoveInstructs(First, Last: Pai);
  1081. {Removes the marked instructions and disposes the PPaiProps of the other
  1082.  instructions, restoring theirline number}
  1083. Var p, hp1: Pai;
  1084.     TmpLine, InstrCnt: Longint;
  1085. Begin
  1086.   p := First;
  1087.   InstrCnt := 1;
  1088.   While (p <> Pai(Last^.Next)) Do
  1089.     If PPaiProp(p^.line)^.CanBeRemoved
  1090.       Then
  1091.         Begin
  1092.           If (InstrCnt > NrOfPaiFast) Then
  1093.             Dispose(PPaiProp(p^.Line));
  1094.           hp1 := Pai(p^.Next);
  1095.           AsmL^.Remove(p);
  1096.           Dispose(p, Done);
  1097.           p := hp1;
  1098.           Inc(InstrCnt)
  1099.         End
  1100.       Else
  1101.         Begin
  1102.           If (InstrCnt > NrOfPaiFast)
  1103.             Then
  1104.               Begin
  1105.                 TmpLine := PPaiProp(p^.Line)^.LineSave;
  1106.                 Dispose(PPaiProp(p^.Line));
  1107.                 p^.Line := TmpLine;
  1108.               End
  1109.             Else p^.Line := PPaiProp(p^.Line)^.LineSave;
  1110.           p := Pai(p^.Next);
  1111.           Inc(InstrCnt)
  1112.         End;
  1113.   If (NrOfPaiFast > 0) Then
  1114. {$IfDef TP}
  1115.     Freemem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+1)div 2)*2))
  1116. {$Else}
  1117.     FreeMem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+3)div 4)*4))
  1118. {$EndIf TP}
  1119. End;
  1120.  
  1121. Function InitReloadOpt(AsmL: PAasmOutput): Boolean;
  1122. {reserves memory for the PPaiProps in one big memory block when not using
  1123.  TP, returns False if not enough memory is available for the optimizer in all
  1124.  cases}
  1125. Var p: Pai;
  1126. Begin
  1127.   P := Pai(AsmL^.First);
  1128.   NrOfPaiObjs := 1;
  1129.   While (P <> Pai(AsmL^.Last)) Do
  1130.     Begin
  1131.       Inc(NrOfPaiObjs);
  1132.       P := Pai(P^.next)
  1133.     End;
  1134. {$IfDef TP}
  1135.   If (MemAvail < (SizeOf(TPaiProp)*NrOfPaiObjs))
  1136.     {this doesn't have to be one contiguous block}
  1137.     Then InitReloadOpt := False
  1138.     Else
  1139.       Begin
  1140.         InitReloadOpt := True;
  1141.         If (MaxAvail < 65520)
  1142.           Then NrOfPaiFast := MaxAvail Div (((SizeOf(TPaiProp)+1) div 2)*2)
  1143.           Else NrOfPaiFast := 65520 Div (((SizeOf(TPaiProp)+1) div 2)*2);
  1144.         If (NrOfPaiFast > 0) Then
  1145.            GetMem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+1) div 2)*2));
  1146.       End;
  1147. {$Else}
  1148. {Uncomment the next line to see how much memory the reloading optimizer needs}
  1149. {  Writeln((NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4)));}
  1150. {no need to check mem/maxavail, we've got as much virtual memory as we want}
  1151.   InitReloadOpt := True;
  1152.   GetMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4));
  1153.   InitReloadOpt := True;
  1154.   NrOfPaiFast := NrOfPaiObjs;
  1155.  {$EndIf TP}
  1156. End;
  1157.  
  1158. Var BlockEnd: Pai;
  1159.  
  1160. Begin {ReloadOpt}
  1161.   If InitReloadOpt(AsmL)
  1162.     Then
  1163.       Begin
  1164.         BlockEnd := CreateRegs(Pai(AsmL^.First));
  1165.         OptimizeBlock(Pai(AsmL^.First), BlockEnd);
  1166.         RemoveInstructs(Pai(AsmL^.First), BlockEnd)
  1167.       End;
  1168. End;
  1169.  
  1170. {
  1171.  $Log: aopt386.inc,v $
  1172.  Revision 1.1.1.1  1998/03/25 11:18:12  root
  1173.  * Restored version
  1174.  
  1175.  Revision 1.22  1998/03/24 21:48:29  florian
  1176.    * just a couple of fixes applied:
  1177.         - problem with fixed16 solved
  1178.         - internalerror 10005 problem fixed
  1179.         - patch for assembler reading
  1180.         - small optimizer fix
  1181.         - mem is now supported
  1182.  
  1183.  Revision 1.21  1998/03/11 15:45:35  florian
  1184.    * -Oa problem solved
  1185.  
  1186.  Revision 1.20  1998/03/10 01:17:13  peter
  1187.    * all files have the same header
  1188.    * messages are fully implemented, EXTDEBUG uses Comment()
  1189.    + AG... files for the Assembler generation
  1190.  
  1191.  Revision 1.19  1998/03/09 16:46:27  jonas
  1192.    * fixed bug with uncertain optimizations when moving data among variables using movsl
  1193.  
  1194.  Revision 1.18  1998/03/04 16:42:00  jonas
  1195.    * bugfix in destroyrefs and fixed a potential bug in createregs
  1196.  
  1197.  Revision 1.17  1998/03/03 20:33:29  jonas
  1198.    * TContent record now only occupies 8 bytes anymore
  1199.  
  1200.  Revision 1.15  1998/03/03 01:08:13  florian
  1201.    * bug0105 and bug0106 problem solved
  1202.  
  1203.  Revision 1.14  1998/03/02 21:35:16  jonas
  1204.    * added comments from last update
  1205.  
  1206.  Revision 1.13  1998/03/02 21:29:06  jonas
  1207.    * redesigned TContent record so it occupies only 13 bytes anymore (was about 18)
  1208.    * store TPaiProps of 16 and 8 bit registers in those of the 32 bit regs
  1209.    * fixed a small bug which prevented some optimizes from being performed
  1210.    * store TPaiProps in one big array instead of in seperate records
  1211.    * warning: TP version not tested because I only have TP, not BP (-> no proteced mode apps)
  1212.  
  1213.  Revision 1.12  1998/02/24 21:18:13  jonas
  1214.    * file name back to lower case
  1215.  
  1216.  Revision 1.4  1998/02/24 20:32:12  jonas
  1217.    * added comments from latest commit
  1218.  
  1219.  Revision 1.3  1998/02/24 20:27:51  jonas
  1220.    * if a register is being written to memory, it's contents aren't destroyed
  1221.     (wherever it's been written to, its contents are up-to-date)
  1222.    * changed the order in which some functions/procedure are defined, because some
  1223.     of them are now used by aopt386.pas
  1224.  
  1225.  Revision 1.11  1998/02/19 22:46:54  peter
  1226.    * Fixed linebreaks
  1227.  
  1228.  Revision 1.10  1998/02/13 10:34:31  daniel
  1229.  * Made Motorola version compilable.
  1230.  * Fixed optimizer
  1231.  
  1232.  Revision 1.9  1998/02/12 17:18:49  florian
  1233.    * fixed to get remake3 work, but needs additional fixes (output, I don't like
  1234.      also that aktswitches isn't a pointer)
  1235.  
  1236.  Revision 1.8  1998/02/12 11:49:37  daniel
  1237.  Yes! Finally! After three retries, my patch!
  1238.  
  1239.  Changes:
  1240.  
  1241.  Complete rewrite of psub.pas.
  1242.  Added support for DLL's.
  1243.  Compiler requires less memory.
  1244.  Platform units for each platform.
  1245.  
  1246.  Revision 1.7  1998/02/07 10:11:19  michael
  1247.    * RefsEqual made less harsh:
  1248.  
  1249.        * when something is written to x(%ebp), registers which contain
  1250.          a pointer that isn't "x(%ebp)"-based isn't destroyed
  1251.  
  1252.        * when something is written to a pointer location, registers
  1253.          which contain the contents of x(%ebp) aren't destroyed
  1254.  
  1255.  
  1256.  Revision 1.6  1998/01/12 17:45:20  jonas
  1257.    * merged DisposeProps and RemoveInstructs procedures (speed!)
  1258.  
  1259.  Revision 1.5  1998/01/11 22:51:30  jonas
  1260.    * back to unix linebreaks...(hate it! :)
  1261.  
  1262.  Revision 1.4 1998/01/11 22:50:10  jonas
  1263.    * all floating point store operations now change op1 instead of the fpu regs
  1264.  
  1265.  Revision 1.3  1998/01/11 14:40:04  jonas
  1266.    * bugfix in optimize procedure (too many instructions were removed in certain cases)
  1267.  
  1268.  Revision 1.1  1997/12/30 21:10:34  jonas
  1269.    * changed back to unix/linux line breaks
  1270.  
  1271.  
  1272.   Pre-CVS log:
  1273.  
  1274.  
  1275.    JM   Jonas Maebe
  1276.  
  1277.   + feature added
  1278.   - removed
  1279.   * bug fixed or changed
  1280.  
  1281.   History (started on 2nd December 1997):
  1282.        2nd December 1997:
  1283.          + initial version (JM)
  1284.          + removes redundant "xor %reg, %reg"'s (JM)
  1285.        3rd December 1997:
  1286.          + removes certain redundant movs (still bugged) (JM)
  1287.          * A_REP now destroys ECX
  1288.        4th December 1997:
  1289.          * fixed bugs in mov-removal (still bugged) (JM)
  1290.        5th December 1997:
  1291.          * fixed more bugs in mov-removal (a compiler compiled with these
  1292.            optimizations now can compile itself suyccessfully!) and enhanced
  1293.            it (introducing new bugs, which have to be fixed again...) (JM)
  1294.          * A_AND and A_OR now destroy op2 instead of op1 <g> (JM)
  1295.        6th December 1997:
  1296.          * A_PUSHAD now only destroys ESP instead of all registers (JM)
  1297.          * A_REPE and A_REPNE now also destroy ECX (JM)
  1298.          * Rewrote some procedures so it's a bit more modular and easier/
  1299.            cleaner/possible to do some optimizations, but it's slower (JM)
  1300.          * enabled mov-reloading optimization for A_MOVZX and A_MOVSX
  1301.            (actually it's already 7 December, 1:25 am in the mean time :) (JM)
  1302.        7th December 1997:
  1303.          * All instructions okayed by CheckSequence are now being removed (JM)
  1304.  
  1305.  
  1306.        To Do:
  1307.          * special case for A_XCHG
  1308.          * implementation of ModReg comparing
  1309.          * special case for lea
  1310.          * fpu optimizing
  1311.          * active optimizing (ie. change certain register allocations)
  1312.          * make DestroyRefs a little less harsh
  1313.          * bug fixes?
  1314. }
  1315.